package jmine.tec.services.io;

import java.util.TreeSet;

import jmine.tec.services.api.ActionsEnum;
import bancosys.tec.utils.date.Date;
import bancosys.tec.utils.date.DateUtils;

import com.thoughtworks.xstream.converters.Converter;
import com.thoughtworks.xstream.converters.MarshallingContext;
import com.thoughtworks.xstream.converters.UnmarshallingContext;
import com.thoughtworks.xstream.io.HierarchicalStreamReader;
import com.thoughtworks.xstream.io.HierarchicalStreamWriter;

/**
 * Conversor de XStream para service bean.
 * 
 * @author Marcio Ribeiro (mmr)
 * @created Jun 20, 2008
 */
public class ServiceBeanXStreamConverter implements Converter {
    private static final String PARAM_NODE = "param";

    private static final String NAME_ATTRIBUTE = "name";

    private static final String ACTION_ATTRIBUTE = "action";

    private static final String LOCATION_ATTRIBUTE = "serviceLocation";

    /**
     * Monta XML a partir de dados de mapa.
     * 
     * @param source mapa.
     * @param writer escritor de xml.
     * @param context contexto.
     */
    public void marshal(Object source, HierarchicalStreamWriter writer, MarshallingContext context) {
        ServiceBean serviceBean = (ServiceBean) source;

        writer.addAttribute(NAME_ATTRIBUTE, serviceBean.getName());
        writer.addAttribute(ACTION_ATTRIBUTE, serviceBean.getAction() == null ? "" : serviceBean.getAction().name());

        if (serviceBean.getServiceLocation() != null) {
            writer.addAttribute(LOCATION_ATTRIBUTE, serviceBean.getServiceLocation());
        }

        for (String key : new TreeSet<String>(serviceBean.getParameters().keySet())) {
            if (key == null || key.trim().equals("")) {
                continue;
            }
            String value = this.convertParamValue(serviceBean.getParameters().get(key));
            writer.startNode(PARAM_NODE);
            writer.addAttribute(NAME_ATTRIBUTE, key);
            writer.setValue(value);
            writer.endNode();
        }
    }

    /**
     * Monta mapa a partir de XML.
     * 
     * @param reader leitor de XML.
     * @param context contexto.
     * @return mapa com dados.
     */
    public Object unmarshal(HierarchicalStreamReader reader, UnmarshallingContext context) {
        ServiceBean serviceBean = new ServiceBean();
        serviceBean.setName(reader.getAttribute(NAME_ATTRIBUTE));
        serviceBean.setAction(ActionsEnum.valueOf(reader.getAttribute(ACTION_ATTRIBUTE)));
        serviceBean.setServiceLocation(reader.getAttribute(LOCATION_ATTRIBUTE));

        while (reader.hasMoreChildren()) {
            reader.moveDown();
            String value = reader.getValue() == null ? null : reader.getValue().trim();
            serviceBean.putParameter(reader.getAttribute(NAME_ATTRIBUTE), value);
            reader.moveUp();
        }

        return serviceBean;
    }

    /**
     * @param clazz classe.
     * @return <code>true</code> se consegue converter, <code>false</code> se nao.
     */
    public boolean canConvert(Class clazz) {
        return clazz.equals(ServiceBean.class);
    }

    /**
     * Converte o valor de um parametro p/ {@link String}.
     * 
     * @param value o valor do parametro
     * @return o valor do parametro na forma de {@link String}
     */
    private String convertParamValue(Object value) {
        if (value == null) {
            return "";
        }
        if (value instanceof Date) {
            return DateUtils.dateToStringDDMMYYYY((Date) value);
        }
        return value.toString();
    }
}
